<?php
/**
 * Created by PhpStorm.
 * User: fengdh
 * Date: 2019/9/4
 * Time: 16:20
 */

namespace search\models;

use business\base\services\DictionaryService;
use business\base\services\QualificationService;
use business\elasticsearch\models\ProcurementModel;
use common\utils\DateTimeUtils;
use common\utils\DomainUtil;
use common\utils\StringUtils;
use function GuzzleHttp\Psr7\str;

class ProcurementSearchForm extends BaseSearchForm
{
    /**
     * @var string 商机类型(招募|招标)
     */
    public $type;

    /**
     * @var string 状态(招募|招标)
     */
    public $state;

    /**
     * @var int 商机所在地
     */
    public $location;

    /**
     * @var int 服务区域
     */
    public $serviceArea;

    /**
     * @var int 供应商类型
     */
    public $supplierType;

    /**
     * @var int 开发商类型(百强|五百强)
     */
    public $developerType;

    /**
     * @var int 注册资本要求
     */
    public $registerFundStart;
    public $registerFundEnd;

    /**
     * @var int 案例要求
     */
    public $caseNum;

    /**
     * @var int 服务资质
     */
    public $priority;

    /**
     * @var int 服务分类
     */
    public $category;
    /**
     * @var string 商机发布时间
     */
    public $pDateSort;

    /**
     * @var string 商机截止时间
     */
    public $dueDateSort;

    /**
     * @var string 有效的商机
     */
    public $valid;
    /**
     * @var string 即将过期
     */
    public $expiringSoon;
    /**
     * @var string 筛选出在若干天内的招标招募，例如180天。
     */
    public $withinXDays;

    /**
     * @var int 企业类型
     */
    public $enterpriseNature;

    /**
     * @var string 过滤租户id
     */
    public $filterTenantId;

    public function rules()
    {
        return [
            [array_keys($this->getAttributes()), 'safe'],
        ];
    }

    public function search()
    {
        $query = [];
        $condition = $this->constructCondition($this->constructFilter($query));
        $query = ProcurementModel::find()->query($condition);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields"=>[
                'sjTitle' => new \stdClass(),
                'sjBasicCategoryName3' => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
//        $sort = [];
        // 默认排序
//        if (empty($this->keyword)) {
//            $sort = ['sjIsExpired' => SORT_ASC, 'sjPublishDate' => SORT_DESC];
//        }
        // 指定发布时间排序
//        if ($this->pDateSort == 1) {
//            $sort=['sjPublishDate' => SORT_DESC];
//        }
        // 指定截止升序
//        if ($this->dueDateSort == 1) {
//            $sort=['sjDueDate' => SORT_ASC];
//        }
//        if ($this->dueDateSort == 2 && empty($this->keyword)) {
//            $sort=['sjDueDate' => SORT_DESC];
//        }
//        if (!empty($sort)) {
//            $query->orderBy($sort);
//        }
        $total = $query->count();

        //分页处理
        $query->offset(($this->page - 1) * $this->pageSize)->limit($this->pageSize);
        $data = $query->asArray()->all();

        $result = ['resultNum' => $total, 'resultSet' => []];
        foreach ($data as $dv) {
            $tmp = $dv['_source'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    if ($key == 'sjTitle') {   //此处为迁移过来的遗留问题，并不合理，因时间问题后续修改
                        $tmp[$key . 'Hl'] = isset($value[0]) ? $value[0] : '';
                    } elseif ($key == 'sjBasicCategoryName3') {
                        $tmp[$key . 'HL'] = !empty($value) ? $value : [];
                    }
                }
            }
            if (!isset($tmp['sjBasicCategoryName3HL'])) {   //此处为迁移过来的遗留问题，并不合理，因时间问题后续修改
                $tmp['sjBasicCategoryName3HL'] = $tmp['sjBasicCategoryName3'];
            }
            $result['resultSet'][] = $tmp;
        }

        //添加搜索记录
        if ((int)$this->page === 1) {
            $this->addSearchRecord($this->keyword, $this->keyword, $result["resultNum"], "procurement", $this->portal);
        }
        return $result;
    }

    public function search2(array $categoryCode, int $page, int $pageSize, $sj_type='recruit', $can_reg=true)
    {
        $condition['function_score']['query']['bool']['must'] = [
            [
                'match' => [
                    'sjType' => $sj_type
                ]
            ]
        ];
        //是否未到截止时间可报名
        if ($can_reg) {
            $condition['function_score']['query']['bool']['must'][] = [
                'range' => [
                    'sjDueDateTimestamp' => [
                        'gt' => time()
                    ]
                ]
            ];
        }
        $condition['function_score']['functions'] = [
            [
                'script_score' => [
                    'script' => "def base = 1; def sjPublishDateTimestamp = doc['sjPublishDateTimestamp'].value; def sjDueDateTimestamp = doc['sjDueDateTimestamp'].value; if (doc['sjIsExpired'].value == 0) {base = 10} return sjPublishDateTimestamp * base;",
                ]
            ]
        ];

        if ($categoryCode) {
            $condition['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    'sjBasicCategoryCode3' => $categoryCode,
                ]
            ];
        }

        $query = ProcurementModel::find()->query($condition);
        $query->source(['sjId', 'sjTitle', 'sjRegisterFund', 'sjBasicCategoryName3', 'sjServiceAreaName', 'sjDueDateTimestamp', 'sjPublishDate','sjDeveloperLogo','sjItemType','sjIsExpired', 'sjType','sjDeveloperId']);
        $query->offset(($page - 1) * $this->pageSize)->limit($pageSize);
        $list = $query->asArray()->all();

        $fieldMap = [
            'sjId' => 'item_id',
            'sjRegisterFund' => 'register_fund',
            'sjServiceAreaName' => 'service_area_name',
            'sjBasicCategoryName3' => 'category_name',
            'sjTitle' => 'title',
            'sjDueDateTimestamp' => 'due_date',
            'sjPublishDate' => 'publish_date',
            'sjDeveloperLogo' => 'developer_logo',
            'sjItemType' => 'item_type',
            'sjIsExpired' => 'is_expired',
            'sjType' => 'type',
            'sjDeveloperId' => 'developer_id'
        ];
        $data = [];
        foreach($list as $key => $item) {
            foreach ($item['_source'] as $subKey => $subItem) {
                if ($subKey == 'sjId') {
                    $subItem = substr($subItem, 8);
                } elseif ($subKey == 'sjDueDateTimestamp') {
                    $subItem = date("Y-m-d H:i:s", $subItem);
                }elseif ($subKey == 'sjPublishDate') {
                    $subItem = date("Y-m-d H:i:s", strtotime($subItem));
                }
                $data[$key][$fieldMap[$subKey]] = $subItem;
            }
            $data[$key]['developer_logo_url']  = DomainUtil::getImgDynamicDomainLink("ImgStatic", '/company/' .
                $data[$key]['developer_id'] . '.200x100.jpg?v=' . (!empty($data[$key]['developer_logo']) ? $data[$key]['developer_logo'] : ''));
        }

        return $data;
    }

    private function constructFilter($query)
    {
        //商机类型  (招募|招标)
        if (!empty($this->type)) {
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getSjType($this->type);
        }
        //供应商类型要求
        if (!empty($this->supplierType)) {
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getSupplierType($this->supplierType);
        }

        //开发商类型(百强|五百强)
        if (isset($this->developerType) && is_numeric($this->developerType)) {
            if ($this->developerType == 0) {
                $developer_type = ['普通', '500强'];
            } elseif ($this->developerType == 100) {
                $developer_type = ['100强'];
            } elseif ($this->developerType == 500) {
                $developer_type = ['100强', '500强'];
            }
            if (!empty($developer_type)) {
                $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getDeveloperType($developer_type);
            }
        }
        if (!empty($this->location)) {
            $locationCodes = [$this->location];
            foreach (explode(',', $this->location) as $locationCode){
                $dictionaryService = new DictionaryService();
                $region = $dictionaryService->getRegionHierarchyByCode($locationCode);
                if (!empty($region) && !empty($region->childRegionNodes)) {
                    foreach ($region->childRegionNodes as $childRegion) {
                        $locationCodes[] = $childRegion->code;
                    }
                }
            }
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getLocationCode($locationCodes);
        }
        //报名服务区域要求
        if (!empty($this->serviceArea)) {
//            $filterServiceAreaCode = is_array($this->serviceArea) ? $this->serviceArea : [$this->serviceArea];
            $dictionaryService = new DictionaryService();
            //报名服务区域调整为可多选
            $filterServiceAreaName = [];//$dictionaryService->getRegionHierarchyByCode($this->serviceArea)->name;

            foreach (explode(',', $this->serviceArea) as $serviceArea){
                $dictionaryService = new DictionaryService();
                $region = $dictionaryService->getRegionHierarchyByCode($serviceArea);
                $filterServiceAreaName[] = $region->name ?: '';
                if (!empty($region) && !empty($region->childRegionNodes)) {
                    foreach ($region->childRegionNodes as $childRegion) {
//                        $filterServiceAreaCode[] = $childRegion->code;
                        $filterServiceAreaName[] = $childRegion->name;
                    }
                }
            }
            $filterServiceAreaName = array_values(array_unique($filterServiceAreaName));
            if (!empty(current($filterServiceAreaName))) {
                //            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getServiceAreaCode($filterServiceAreaCode);
                $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getServiceAreaName($filterServiceAreaName);
            }
        }
        //注册资本要求
        if (!empty($this->registerFundStart) || !empty($this->registerFundEnd)) {
            $registerFundStart = !empty($this->registerFundStart) ? $this->registerFundStart : 0;
            $registerFundEnd = !empty($this->registerFundEnd) ? $this->registerFundEnd : null;
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getRegisterFund($registerFundStart, $registerFundEnd);
        }
        //案例要求
        if (!empty($this->caseNum) && $this->caseNum > 0) {
            $caseNumMin = $caseNumMax = null;
            switch ($this->caseNum) {
                case 1:
                    $caseNumMin = $this->caseNum;
                    break;
                case 3:
                    $caseNumMin = $this->caseNum;
                    break;
                case 5:
                    $caseNumMin = $this->caseNum;
                    break;
                case 99:
                    $caseNumMin = 0;
                    $caseNumMax = 0;
                    break;
                default:
            }
            if ($caseNumMin!==null || $caseNumMax!==null) {
                $query['function_score']['query']['bool']['filter'][] = ProcurementModel::getCaseNum($caseNumMin, $caseNumMax);
            }
        }
        //服务分类要求
        if (!empty($this->category)) {
            $query['function_score']['query']['bool']['must'][] = ["terms" => ["sjBasicCategoryCode3" => explode(',', $this->category)]];
        }
        if (!empty($this->filterTenantId)) {
            $query['function_score']['query']['bool']['must_not'][] = ["terms" => ["tenantId" => explode(',', $this->filterTenantId)]];
        }
        //一级分类code查询过滤
        if (!empty($this->codeLevel1)) {
            $query['function_score']['query']['bool']['filter'][] = ["terms" => ["sjBasicCategoryCode1" => explode(',', $this->codeLevel1)]] ;
        }
        //二级分类code查询过滤
        if (!empty($this->codeLevel2)) {
            $query['function_score']['query']['bool']['filter'][] = ["terms" => ["sjBasicCategoryCode2" => explode(',', $this->codeLevel2)]] ;
        }
        //三级分类code查询过滤
        if (!empty($this->codeLevel3)) {
            $query['function_score']['query']['bool']['filter'][] = ["terms" => ["sjBasicCategoryCode3" => explode(',', $this->codeLevel3)]] ;
        }
        // 有效，无效
        if (isset($this->valid) && $this->valid !== '') { // valid字段是PC端专属字段；1：报名中 2：已截止
            $is_expired = $this->valid == 1 ? 0 : 1;
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::sjIsExpired($is_expired);
        }
        // 报名状态 0:未截止 1:已截止
        if (isset($this->state) && $this->state != '') { // state字段是移动端专属字段; 0: 报名中 1：已截止
            $is_expired = $this->state == 0 ? 0 : 1;
            $query['function_score']['query']['bool']['filter'][] = ProcurementModel::sjIsExpired($is_expired);
        }
        // 企业类型查询过滤
        if (is_numeric($this->enterpriseNature) && $this->enterpriseNature > 0) {
            $query['function_score']['query']['bool']['filter'][] = [
                'term' => ['enterpriseNature' => $this->enterpriseNature]
            ];
        }

        // X天内的招标招募
        if (!empty($this->withinXDays)) {
            $query['function_score']['query']['bool']['filter'][] = ['range' => ['sjPublishDate' => ['from'=>date('Y-m-d', strtotime('-'.$this->withinXDays.' days'))]]];
        }
        return $query;
    }

    private function constructCondition($query)
    {
        if (!empty($this->keyword)) {
            $query['function_score']['query']['bool']['should'] = [
                ['match' => ['sjSearchDeveloperName' => ['query' => $this->keyword, 'boost'=>1, 'analyzer'=>'ik_smart']]],
                ['match' => ['sjTitle' => ['query' => $this->keyword, 'boost'=>1, 'analyzer'=>'ik_smart']]],
                ['match' => ['sjSearchBasicCategoryName3' => ['query' => $this->keyword, 'boost'=>1, 'analyzer'=>'ik_smart']]],
                ['match_phrase' => ['sjTitle' => ['query' => $this->keyword, 'boost'=>10,'slop' => 2]]],
                ['match_phrase' => ['sjTitle.keyword' => ['query' => $this->keyword, 'boost'=>4000000000]]],
            ];
        }
        if (!empty($query['function_score']['query']['bool']['should'])) {
            $query['function_score']['query']['bool']['minimum_should_match'] = 1;
        }

        $query['function_score']['query']['bool']['must'] = [
            ['range' => ['sjPublishDateTimestamp' => ['gt' => 0]]],
        ];

//        $curTime = time();
        $query['function_score']['functions'] = [
            [
                'script_score' => [
//                    'script' => "def base = 1; def sjPublishDateTimestamp = doc['sjPublishDateTimestamp'].value; def sjDueDateTimestamp = doc['sjDueDateTimestamp'].value; if (sjDueDateTimestamp > {$curTime}) {base = 100} return Math.log(1 + {$curTime}/({$curTime} - sjPublishDateTimestamp)) * base;",
                    'script' => "def base = 1; def sjPublishDateTimestamp = doc['sjPublishDateTimestamp'].value; def sjDueDateTimestamp = doc['sjDueDateTimestamp'].value; if (doc['sjIsExpired'].value == 0) {base = 10} return sjPublishDateTimestamp * base;",
                ]
            ]
        ];

        $query['function_score']['score_mode'] = 'sum';
        $query['function_score']['boost_mode'] = 'sum';
        return $query;
    }

}